package com.xhwl.data.controller;


import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xhwl.common.dto.cent.sdata.OrganizationDTO;
import com.xhwl.common.dto.cent.sdata.RoomDTO;
import com.xhwl.common.enums.OrganizationTypeEnum;
import com.xhwl.common.enums.RoomOrientationEnum;
import com.xhwl.common.enums.config.IndustryEnum;
import com.xhwl.common.enums.space.RoomStatusEnum;
import com.xhwl.common.enums.space.ViewType;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.sdata.*;
import com.xhwl.common.pojo.cent.sdata.space.RoomOperateLog;
import com.xhwl.common.query.cent.sdata.OrganizationQuery;
import com.xhwl.common.query.cent.sdata.RoomQuery;
import com.xhwl.data.dao.IRoomDao;
import com.xhwl.data.pojo.space.RoomCheck;
import com.xhwl.data.pojo.space.RoomOperateDTO;
import com.xhwl.data.service.*;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author: luyi
 * @Description:
 * @Date: Create in 11:30 2021/1/23
 */
@RestController
public class RoomController {

    @Autowired
    private IRoomService roomService;

    @Autowired
    private IRoomDao roomDao;

    @Autowired
    private IOrganizationService organizationService;

    @Autowired
    private IOrganizationTypeService organizationTypeService;

    @Autowired
    private ISpaceFunctionTypeService spaceFunctionTypeService;

    @Autowired
    private IRoomOperatorLogService roomOperatorLogService;

    private static final Logger log = LoggerFactory.getLogger(RoomController.class);

    @RequestMapping(value = "/room/insert", method = RequestMethod.POST)
    public ResultJson insert(@RequestHeader Short industryId, @RequestBody RoomDTO room, Account account) {

        ResultJson check = RoomCheck.check(room);
        if(!check.getState()){
            return check;
        }
        if (null != room.getId()) {
            return roomService.update(room);
        } else {
            if (null == room.getParentId()) {
                return ResultJson.fail("缺少上级信息");
            }
            return roomService.create(room);
        }
    }

    @RequestMapping(value = "/room/batch-insert")
    public ResultJson batchCreate(@RequestBody List<RoomDTO> rooms) {
        if (CollectionUtils.isEmpty(rooms)) {
            return ResultJson.success();
        }
        //校验编码是否唯一
        long count = rooms.stream().map(Room::getCode).distinct().count();
        if(rooms.size() > count){
            return ResultJson.fail("编码重复");
        }
        for (RoomDTO room : rooms) {
            ResultJson check = RoomCheck.check(room);
            if(!check.getState()){
                return check;
            }
        }
        return roomService.batchCreate(rooms);
    }


    @RequestMapping(value = "/room/delete")
    public ResultJson delete(Integer id, Account account) {
        return roomService.delete(id, account);
    }


    @RequestMapping(value = "/room/page")
    public ResultJson page(@RequestBody RoomQuery roomQuery, Page page, Account account) {
        Page<Room> page1 = roomService.page(roomQuery, account, page);
        return ResultJson.success(convertDTO(page1,roomQuery.getTypeId()));
    }


    @RequestMapping(value = "/room/list")
    public ResultJson list(@RequestBody RoomQuery roomQuery) {
        return ResultJson.success(roomService.list(roomQuery));
    }


    @RequestMapping(value = "/room/detail")
    public ResultJson detail(Integer id, Integer orgId, Account account,Integer typeId) {

        if (null == id && null == orgId) {
            return ResultJson.fail("参数错误");
        }
        RoomQuery roomQuery = new RoomQuery();
        roomQuery.withOrgId(orgId).withId(id);
        Room room = roomService.one(roomQuery);
        if (null == room) {
            log.warn("房间数据不存在");
            return ResultJson.success();
        }
        List<SpaceFunctionType> spaceFunctionTypes = listFunctionType();
        RoomDTO roomDTO = processBean(room, spaceFunctionTypes,typeId);
        QueryWrapper<OrganizationType> organizationTypeQueryWrapper = new QueryWrapper<>();
        organizationTypeQueryWrapper.in("view_type", Arrays.asList(ViewType.SPACE, ViewType.SPACE_DEFINED));
        List<OrganizationType> list = organizationTypeService.list(organizationTypeQueryWrapper);

        OrganizationQuery organizationQuery = new OrganizationQuery();
        organizationQuery.withTypes(list.stream().map(i -> i.getId()).collect(Collectors.toList()));
        organizationQuery.withId(room.getOrganizationId());
        String s = organizationService.fullName(organizationQuery);
        roomDTO.setFullName(s);
        setOperateLogs(roomDTO);
        return ResultJson.success(roomDTO);
    }

    private void setOperateLogs(RoomDTO roomDTO) {
        QueryWrapper<RoomOperateLog> roomOperateLogQueryWrapper = new QueryWrapper<>();
        roomOperateLogQueryWrapper.eq("new_room_id", roomDTO.getId());
        List<RoomOperateLog> list = roomOperatorLogService.list(roomOperateLogQueryWrapper);
        roomDTO.setLogList(list);
    }

    @RequestMapping(value = "/room/status")
    public ResultJson status(@RequestHeader Short industryId) {
        RoomStatusEnum[] values = RoomStatusEnum.values();
        List<RoomStatusEnum> collect = Arrays.asList(values);
        List<Map<Object, Object>> result = collect.stream().map(i -> {
            Map<Object, Object> map = new HashMap<>();
            map.put("id", i.id);
            map.put("name", i.description);
            map.put("code", i);
            return map;
        }).collect(Collectors.toList());
        return ResultJson.success(result);
    }


    @RequestMapping("/room/count-status")
    public ResultJson countStatus(@RequestBody RoomQuery roomQuery) {
        if (null == roomQuery.getParentId()) {
            return ResultJson.fail("参数错误");
        }
        List<Map<String, Object>> result = new ArrayList<>();
        OrganizationQuery organizationQuery = new OrganizationQuery();
        organizationQuery.withId(roomQuery.getParentId());
        organizationQuery.withRoundLevel(-10);
        organizationQuery.withTypes(Arrays.asList(OrganizationTypeEnum.ROOM.id.intValue()));
        // parentId 下面所有的房间
        List<Organization> child = organizationService.child(organizationQuery);
        if (child.isEmpty()) {
            for (RoomStatusEnum value : RoomStatusEnum.values()) {
                Map<String, Object> map = new HashMap<>();
                map.put("name", value.name());
                map.put("value", null);
                result.add(map);
            }
            return ResultJson.success(result);
        }
        List<Integer> roomOrgId = child.stream().map(i -> i.getId()).collect(Collectors.toList());
        roomQuery.setOrgIds(roomOrgId);
        List<Room> rooms = roomDao.roomPicList(roomQuery);
        for (RoomStatusEnum value : RoomStatusEnum.values()) {
            long count = rooms.stream().filter(i -> (null != i.getStatus() && i.getStatus().id.equals(value.id))).count();
            Map<String, Object> map = new HashMap<>();
            map.put("name", value.name());
            map.put("value", count);
            result.add(map);
        }
        return ResultJson.success(result);
    }


    /**
     * 租控图接口 （这里固定生成两级结构，最下面一级是房间）
     *
     * @param roomQuery
     * @return
     */
    @RequestMapping("/room/status-pic")
    public ResultJson statusPic(@RequestBody RoomQuery roomQuery) {
        if (null == roomQuery.getParentId()) {
            return ResultJson.fail("参数错误");
        }
        Organization parent = organizationService.getById(roomQuery.getParentId());
        if (null == parent) {
            return ResultJson.fail("上级不存在");
        }
        List<Integer> levels = Arrays.asList(parent.getLevel() + 1, parent.getLevel() + 2);
        OrganizationQuery organizationQuery = new OrganizationQuery();
        organizationQuery.setId(roomQuery.getParentId());
        List<Organization> child = organizationService.child(organizationQuery);
        if (child.isEmpty()) {
            log.info("暂无匹配数据");
            return ResultJson.success();
        }
        // 获取下两级的层级
        List<Organization> childLevel2 = child.stream().filter(i -> levels.contains(i.getLevel())).collect(Collectors.toList());
        if (childLevel2.isEmpty()) {
            log.info("暂无匹配数据");
            return ResultJson.success();
        }
        List<Organization> roomNodes = childLevel2.stream().filter(i -> i.getType().intValue() == OrganizationTypeEnum.ROOM.id.intValue()).collect(Collectors.toList());
        if (roomNodes.isEmpty()) {
            log.info("暂无匹配的房间数据");
            return ResultJson.success();
        }
        QueryWrapper<Room> roomQueryWrapper = new QueryWrapper<>();
        roomQueryWrapper.select("id", "name", "status", "area", "organization_id");
        roomQueryWrapper.in("organization_id", roomNodes.stream().map(i -> i.getId()).collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(roomQuery.status)) {
            roomQueryWrapper.in("status", roomQuery.status);
        }
        if (null != roomQuery.getMaxArea()) {
            roomQueryWrapper.lt("area", roomQuery.getMaxArea());
        }
        if (null != roomQuery.getMinArea()) {
            roomQueryWrapper.gt("area", roomQuery.getMinArea());
        }
        List<Room> rooms = roomService.list(roomQueryWrapper);
        Map<Integer, Room> roomMap = rooms.stream().collect(Collectors.toMap(Room::getOrganizationId, Function.identity()));
        Map<Integer, List<Room>> parentIdRoomMap = new HashMap<>();
        for (Organization roomNode : roomNodes) {
            List<Room> rooms1 = parentIdRoomMap.get(roomNode.getParentId());
            if (CollectionUtils.isEmpty(rooms1)) {
                List<Room> childRoom = new ArrayList<>();
                childRoom.add(roomMap.get(roomNode.getId()));
                parentIdRoomMap.put(roomNode.getParentId(), childRoom);
            } else {
                Room room = roomMap.get(roomNode.getId());
                rooms1.add(room);
            }
        }
        List<RoomPicDTO> level1 = childLevel2.stream().filter(i -> i.getLevel().equals(parent.getLevel() + 1)).map(i -> {
            RoomPicDTO roomPicDTO = new RoomPicDTO();
            BeanUtils.copyProperties(i, roomPicDTO);
            return roomPicDTO;
        }).collect(Collectors.toList());
        for (RoomPicDTO roomPicDTO : level1) {
            roomPicDTO.setChild(parentIdRoomMap.get(roomPicDTO.getId()));
        }
        return ResultJson.success(level1);
    }


    @RequestMapping("/room/space-choose")
    public ResultJson roomSpaceChoose(@RequestBody RoomQuery roomQuery) {
        if (null == roomQuery.getProjectId()) {
            return ResultJson.fail("参数错误");
        }
        QueryWrapper<Organization> roomQueryWrapper = new QueryWrapper<>();
        roomQueryWrapper.select("id");
        roomQueryWrapper.in("project_id", roomQuery.projectId);
        roomQueryWrapper.eq("type", OrganizationTypeEnum.ROOM.id);
        List<Organization> rooms = organizationService.list(roomQueryWrapper);
        if (rooms.isEmpty()) {
            return ResultJson.success();
        }
        QueryWrapper<OrganizationType> organizationTypeQueryWrapper = new QueryWrapper<>();
        organizationTypeQueryWrapper.in("view_type", Arrays.asList(ViewType.SPACE, ViewType.SPACE_DEFINED));
        List<OrganizationType> list = organizationTypeService.list(organizationTypeQueryWrapper);
        List<Integer> roomOrgId = rooms.stream().map(i -> i.getId()).collect(Collectors.toList());
        OrganizationQuery organizationQuery = new OrganizationQuery();
        organizationQuery.withIds(roomOrgId);
        organizationQuery.withRoundLevel(10);
        organizationQuery.withTypes(list.stream().map(i -> i.getId()).collect(Collectors.toList()));
        List<OrganizationDTO> tree = organizationService.tree(organizationQuery);
        return ResultJson.success(tree);
    }


    /**
     * 房间类型业态占比统计（按房间类型统计建筑面积占比）
     *
     * @param organizationQuery
     * @return
     */
    @RequestMapping(value = "/room-type-proportion/statistics", method = RequestMethod.POST)
    public ResultJson statistics(
            @RequestHeader Short industryId,
            @RequestBody OrganizationQuery organizationQuery) {
        return roomService.roomTypeProportionStatistics(industryId, organizationQuery.getIds());
    }

    /**
     * 房间朝向
     *
     * @return
     */
    @GetMapping("/room/list-orientation")
    public ResultJson listOrientation() {
        List<JSONObject> jsonObjects = new ArrayList<>();
        for (RoomOrientationEnum orientation : RoomOrientationEnum.values()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("name", orientation.getDescription());
            jsonObject.put("code", orientation);
            jsonObjects.add(jsonObject);
        }
        return ResultJson.success(jsonObjects);
    }

    /**
     * 获取当前编码
     *
     * @return
     */
    @GetMapping("/room/get-current-code")
    public ResultJson getCurrentCode() {
        return ResultJson.success().setResult(roomService.getCurrentCode());
    }

    /**
     * 房间拆分
     * @return
     */
    @PostMapping("/room/split")
    public ResultJson split(@RequestBody RoomOperateDTO roomOperateDTO){
        return roomService.split(roomOperateDTO);
    }

    /**
     * 房间合并
     * @return
     */
    @PostMapping("/room/merge")
    public ResultJson merge(@RequestBody RoomOperateDTO roomOperateDTO){
        return roomService.merge(roomOperateDTO);
    }

    public Page convertDTO(Page page,Integer typeId) {
        if (page.getRecords().isEmpty()) {
            return page;
        }
        List<Room> source = page.getRecords();
        List<RoomDTO> result = new ArrayList<>(source.size());
        List<SpaceFunctionType> spaceFunctionTypes = listFunctionType();
        for (Room room : source) {
            RoomDTO roomDTO = processBean(room, spaceFunctionTypes,typeId);
            result.add(roomDTO);
        }
        return page.setRecords(result);
    }


    @Data
    class RoomPicDTO extends Organization {

        private List<Room> child;
    }

    private RoomDTO processBean(Room room, List<SpaceFunctionType> spaceFunctionTypes,Integer typeId) {
        RoomDTO roomDTO = new RoomDTO();
        BeanUtils.copyProperties(room, roomDTO);
        //填充功能名称
        if (null != roomDTO.getFunctionType()) {
            for (SpaceFunctionType spaceFunctionType : spaceFunctionTypes) {
                if (spaceFunctionType.getId().equals(roomDTO.getFunctionType())) {
                    roomDTO.setFunctionName(spaceFunctionType.getName());
                    break;
                }
            }
        }
        if (null != room.getStatus()) {
            roomDTO.setStatusName(room.getStatus().description);
        }
        if (null != room.getOrientation()) {
            roomDTO.setOrientationName(room.getOrientation().getDescription());
        }
        dealJson(roomDTO,typeId);
        return roomDTO;
    }

    /**
     * 兼容历史数据
     */
    private void dealJson (Room param,Integer typeId){
        if(typeId == null){
            return;
        }
        QueryWrapper<OrganizationType> organizationTypeQueryWrapper = new QueryWrapper<>();
        organizationTypeQueryWrapper.eq("id", typeId);
        OrganizationType organizationType = organizationTypeService.getOne(organizationTypeQueryWrapper);
        String source = organizationType.getSource();
        if(StringUtils.isEmpty(source)){
            return;
        }
        Map<String,Object> map = new HashMap<>();
        JSONObject sourceJson = JSON.parseObject(source);
        JSONArray fields = sourceJson.getJSONArray("fields");
        if(CollectionUtil.isNotEmpty(fields)) {
            for (int i = 0; i < fields.size(); i++) {
                JSONObject fieldJsonObject = fields.getJSONObject(i);
                fieldJsonObject.remove("__config__");
                String vModel = fieldJsonObject.getString("vModel");
                //兼容以前数据
                if ("name".equals(vModel)) {
                    fields.getJSONObject(i).put("defaultValue",param.getName() != null ? param.getName() : "");
                    map.put("name",param.getName() != null ? param.getName() : "");
                } else if ("code".equals(vModel)) {
                    fields.getJSONObject(i).put("defaultValue",param.getCode() != null ? param.getCode() : "");
                    map.put("code",param.getCode() != null ? param.getCode() : "");
                } else if ("area".equals(vModel)) {
                    fields.getJSONObject(i).put("defaultValue",param.getArea() != null ? param.getArea() : "");
                    map.put("area",param.getArea() != null ? param.getArea() : "");
                } else if ("status".equals(vModel)) {
                    fields.getJSONObject(i).put("defaultValue",param.getStatus() != null ? param.getStatus() : "");
                    map.put("status",param.getStatus() != null ? param.getStatus() : "");
                } else if ("orientation".equals(vModel)) {
                    fields.getJSONObject(i).put("defaultValue",param.getOrientation() != null ? param.getOrientation() : "");
                    map.put("orientation",param.getOrientation() != null ? param.getOrientation() : "");
                } else if ("insideSpace".equals(vModel)) {
                    fields.getJSONObject(i).put("defaultValue",param.getInsideSpace() != null ? param.getInsideSpace() : "");
                    map.put("insideSpace",param.getInsideSpace() != null ? param.getInsideSpace() : "");
                } else if ("usableArea".equals(vModel)) {
                    fields.getJSONObject(i).put("defaultValue",param.getUsableArea() != null ? param.getUsableArea() : "");
                    map.put("usableArea",param.getUsableArea() != null ? param.getUsableArea() : "");
                } else if ("residentialPoolArea".equals(vModel)) {
                    fields.getJSONObject(i).put("defaultValue",param.getResidentialPoolArea() != null ? param.getResidentialPoolArea() : "");
                    map.put("residentialPoolArea",param.getResidentialPoolArea() != null ? param.getResidentialPoolArea() : "");
                } else if ("sortField".equals(vModel)){
                    fields.getJSONObject(i).put("defaultValue",param.getSortField() != null ? param.getSortField() : "");
                    map.put("sortField",param.getSortField() != null ? param.getSortField() : "");
                } else {
                    if(param.getExpand() != null) {
                        JSONObject jsonObject = JSON.parseObject(param.getExpand());
                        if(jsonObject.get(vModel) != null) {
                            fields.getJSONObject(i).put("defaultValue", jsonObject.get(vModel));
                            map.put(vModel,jsonObject.get(vModel));
                        }else{
                            map.put(vModel,"");
                        }
                    }else{
                        map.put(vModel,"");
                    }
                }
            }
        }
        param.setExpand(JSON.toJSONString(sourceJson));
        param.setFullData(JSON.toJSONString(map));
    }


    private List<SpaceFunctionType> listFunctionType() {
        return spaceFunctionTypeService.list(new QueryWrapper<SpaceFunctionType>()
                .eq("org_type", OrganizationTypeEnum.ROOM.getId()));
    }
}

